package com.bubbo.rpc.client;

import com.bubbo.discoverCenter.ServiceDiscover;
import com.bubbo.rpc.client.bean.RpcRequest;
import com.bubbo.rpc.client.bean.RpcResponse;
import com.bubbo.rpc.client.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;

import java.lang.reflect.Method;
import java.util.UUID;

/**
 * Created by waasdasd on 2017/3/31.
 */
public class BubboProxy {
    private Logger logger = LoggerFactory.getLogger(BubboProxy.class);

    private String serviceAddress;
    private ServiceDiscover serviceDiscover;

    public BubboProxy(String serviceAddress) {
        this.serviceAddress = serviceAddress;
    }

    public BubboProxy(ServiceDiscover serviceDiscover) {
        this.serviceDiscover = serviceDiscover;
    }

    public <T> T create(final Class<?> interfaceClass) {
        return create(interfaceClass, "");
    }

    public <T> T create(final Class<?> interfaceClass, final String serviceVersion) {
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        RpcRequest request = new RpcRequest();
                        request.setRequestId(UUID.randomUUID().toString());
                        request.setInterfaceName(method.getDeclaringClass().getName());
                        request.setMethodName(method.getName());
                        request.setParameters(objects);
                        request.setParamterType(method.getParameterTypes());
                        if (serviceDiscover != null) {
                            String serviceName = interfaceClass.getName();
                            if (serviceVersion != null) {
                                serviceName += serviceVersion;
                            }
                            serviceAddress = serviceDiscover.discovery(serviceName);
                            String[] array = StringUtil.split(serviceAddress, ":");
                            String host = array[0];
                            int port = Integer.valueOf(array[1]);
                            BubboClient bubboClient = new BubboClient(port, host);
                            RpcResponse response = bubboClient.send(request);
                            if (response == null) {
                                throw new RuntimeException("response is null");
                            }
                            // 返回 RPC 响应结果
                            if (response.hasException()) {
                                throw response.getException();
                            } else {
                                return response.getResult();
                            }
                        }
                        return null;
                    }

                }
        );
    }
}
